<template>
  <div style="text-align: center">
    <!-- 聊天窗口容器 -->
    <div class="page_chart">

      <div id="chatWindow" class="chat-window"></div>
      <div id="canvaWindow" ref="echartsRef" class="canva-window"></div>


      <div class="page_talk_item">
        <button class="talk_btn" type="talk" @click="chat2cozeInit(1)">开始派单</button>
        <button class="talk_btn" type="talk" @click="chat2cozeInit(2)">说明当前点检内容</button>
        <button class="talk_btn" type="talk" @click="chat2cozeInit(3)">说明当前点检要求</button>
        <button class="talk_btn" type="talk" @click="chat2cozeInit(4)">说明点检过程</button>
        <button class="talk_btn" type="talk" @click="chat2cozeInit(5)">查询当前点检项是否有改进措施，并预测改进后的效果</button>
      </div>
    </div>



  </div>
</template>


<script setup>
import { inject, ref, onMounted, nextTick } from "vue";
import { marked } from 'marked'; // 引入marked库
import echarts from "../utils/echartUtil"; // 引入echarts库


let cozeState = inject("cozeState")

/**
 * ------------------------------智能体-----------------------------------
 */


// API 配置
// BOT_ID 在 工作空间 → 发布管理 → 智能体 → 地址栏URL的 /publish/agent/※※※※※※※※※※※※ 中获取
const BOT_ID = "7494090420830666803";
// API_TOKEN 在 扣子API → 授权 → 个人访问令牌 中获取
const API_TOKEN = "pat_NljuabQ6DYFJMwOeQgqEPq0pGKkITOs53EmzS80yZZvGbKgtcN27WFS1WEwnCQng";
const BASE_URL = "https://api.coze.cn/v3";


// 智能体配置
let question = "需要在这里填入想问智能体的问题（注意：问的方式很重要，可以提要求、定规则）";
let userName = "Person2";
let lastProcessedIndex = 0;
let messageContentQueue = []; // 消息内容队列
let isTyping = false; // 标记是否正在打字
// 用于存储当前正在打字的bubble元素
let currentBubbleElement = null;


// 向智能体问问题
function chat2cozeInit(num) {
  if (cozeState.value === true) {
    messageContentQueue = [];
    lastProcessedIndex = 0;
    isTyping = false;
    currentBubbleElement = null;

    document.getElementById('chatWindow').innerHTML = ''; // 清空聊天窗口内容

    switch (num) {
      case 1:
        question = `你好，我是 ${userName}，帮我查询下今天有哪些设备点检项目，只列举 点检内容 即可`
        send_chat_request(question);
        break;
      case 2:
        question = `我是 ${userName}，请基于上方的设备点检内容，详细说明当前点检内容，其它内容无需过分解读。`
        send_chat_request(question);
        break;
      case 3:
        question = `我是 ${userName}，请基于上方的设备点检内容，详细说明当前点检要求，其它内容无需过分解读。`
        send_chat_request(question);
        break;
      case 4:
        question = `我是 ${userName}，请基于上方的设备点检内容，详细说明点检过程，其它内容无需过分解读。`
        send_chat_request(question);
        break;
      case 5:
        question = `我是 ${userName}，请基于上方的设备点检内容，详细查询当前点检项是否有改进措施，并预测改进后的效果，其它内容无需过分解读。`
        send_chat_request(question);
        break;
    }
  } else {
    alert("请先在“用户筛查”功能中，开启摄像头进行人脸识别，确认人员身份")
  }
}





// 发送聊天请求
async function send_chat_request(question) {


  const url = `${BASE_URL}/chat`;
  const headers = {
    "Authorization": `Bearer ${API_TOKEN}`,
    "Content-Type": "application/json"
  };
  const data = {
    "bot_id": BOT_ID,
    "user_id": "user",  // 可以使用任意用户ID
    "stream": true,
    "additional_messages": [
      {
        "role": "user",
        "content": question,
        "content_type": "text"
      }
    ]
  };


  // 发起 对话请求
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(data)
    });


    // 创建可读流
    const reader = response.body.getReader();
    let messageContent = ''; // 用于累积消息内容
    let decoder = new TextDecoder('utf-8');

    // 读取流数据
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        console.log('Stream ended');
        break;
      }
      const chunk = decoder.decode(value, { stream: true });
      messageContent += chunk; // 累积消息内容

      // 处理累积的消息内容
      processMessageContent(messageContent);
    }
  } catch (error) {
    console.error('请求出错:', error);
    return null;
  }

}



// 处理消息内容
function processMessageContent(content) {
  let currentIndex = lastProcessedIndex;
  let eventDeltaIndex = content.indexOf('event:conversation.message.delta', currentIndex);

  while (eventDeltaIndex !== -1) {
    // 找到下一个 'event:conversation.message.delta' 的位置
    let nextEventDeltaIndex = content.indexOf('event:conversation.message.delta', eventDeltaIndex + 1);
    let endEventDeltaIndex = nextEventDeltaIndex !== -1 ? nextEventDeltaIndex : content.length;

    // 提取数据部分，移除"data:"前缀并找到 JSON 对象的结束位置 '}'
    let dataString = content.substring(eventDeltaIndex, endEventDeltaIndex);
    let dataIndex = dataString.indexOf('data:');
    let jsonEndIndex = dataString.indexOf('}', dataIndex) + 1;

    // 确保我们找到了完整的 JSON 对象
    if (jsonEndIndex > 0 && dataString[jsonEndIndex - 1] === '}') {
      try {
        // 尝试解析 JSON 对象
        const dataObject = JSON.parse(dataString.substring(dataIndex + 5, jsonEndIndex));

        // 将消息内容添加到队列中
        messageContentQueue.push(dataObject.content);
        // 处理队列
        processMessageContentQueue();



      } catch (error) {
        console.error('Error parsing JSON:', error);
      }

      // 更新处理位置
      currentIndex = eventDeltaIndex + jsonEndIndex;
      eventDeltaIndex = nextEventDeltaIndex;
    } else {
      // 如果没有找到完整的 JSON 对象，则停止处理
      break;
    }
  }
  lastProcessedIndex = currentIndex;
}

// 处理打印机队列
const processMessageContentQueue = () => {

  if (!isTyping && messageContentQueue.length > 0) {

    const content = messageContentQueue.shift()
    isTyping = true;
    type2Message(content, true); // 开始打字队列中的下一条消息
  }


}



/**
 * 打字机效果
 * @param content 消息内容
 * @param isNewMessage 是否为新消息
 */
const type2Message = (content, isNewMessage) => {

  // 初始化 index 
  let index = 0;

  // 确保元素存在时，进行以下操作
  const chatWindow = document.getElementById('chatWindow');
  if (!chatWindow) {
    console.error('chatWindow 元素不存在');
    return;
  }
  // 如果当前bubble元素不存在，或者消息的方向改变了，创建一个新的bubble元素
  if (!currentBubbleElement || !currentBubbleElement.classList.contains('bubble-left')) {
    currentBubbleElement = document.createElement('div');
    currentBubbleElement.className = 'bubble bubble-left'; // 总是使用'bubble-left'样式
    currentBubbleElement.textContent = ''; // 初始化为空字符串

    // 创建一个新的chat-message元素并添加bubble
    const newMessage = document.createElement('div');
    newMessage.className = `chat-message left`; // 确保消息总是使用'left'样式
    newMessage.appendChild(currentBubbleElement);

    // 将新消息添加到chatWindow
    chatWindow.appendChild(newMessage);
  }

  (function typeNextChar() {

    // 逐字添加内容
    if (content != undefined && index < content.length) {

      // 使用 innerHTML 插入 HTML 内容（如果插入纯文字，使用 textContent ）
      currentBubbleElement.textContent += content[index];
      index++; // 更新索引
      requestAnimationFrame(typeNextChar); // 使用requestAnimationFrame模拟打字效果
    } else {
      isTyping = false; // 打字完成后，将标志设置为 false
      processMessageContentQueue(); // 处理队列中的下一条消息
    }
  })();


}



// ------------------- 路径规划 -------------------------

const echartsRef = ref(null)
onMounted(() => {
  nextTick(() => {
    if (echartsRef.value) {
      // var chartDom = document.getElementById('canvaWindow');
      const myChart = echarts.init(echartsRef.value);
      let option;
      // 注意：项目中svg放到 public 下可通过 / 直接访问
      fetch('/assets/MacOdrum-LV5-floorplan-web.svg')
        .then(response => {
          if (!response.ok) throw new Error('网络响应失败');
          return response.text();
        })
        .then(svg => {
          echarts.registerMap('MacOdrum-LV5-floorplan-web', { svg: svg });
          option = {
            title: {
              text: '路径规划',
              left: 'center',
              bottom: 10,
              textStyle: {
                color: '#FFFFFF',
                fontSize: 14
              }
            },
            tooltip: {},
            geo: {
              map: 'MacOdrum-LV5-floorplan-web',
              roam: true,
              emphasis: {
                itemStyle: {
                  color: '#FFFFFF'
                },
                label: {
                  show: true
                }
              }
            },
            series: [
              {
                name: 'Route',
                type: 'lines',
                coordinateSystem: 'geo',
                geoIndex: 0,
                emphasis: {
                  label: {
                    show: false
                  }
                },
                polyline: true,
                // 线路
                lineStyle: {
                  color: '#FFFFFF',
                  width: 5,
                  opacity: 1,
                  type: 'dotted'
                },
                effect: {
                  show: true,
                  period: 8,
                  color: '#FFFFFF',
                  constantSpeed: 80,
                  trailLength: 0,
                  symbolSize: [20, 12],
                  symbol:
                    `path://M35.5 40.5c0-22.16 17.84-40 40-40s40 17.84 40 40c0 1.6939-.1042 3.3626-.3067 
                    5H35.8067c-.2025-1.6374-.3067-3.3061-.3067-5zm90.9621-2.6663c-.62-1.4856-.9621-3.1182-.9621-4.8337 
                    0-6.925 5.575-12.5 12.5-12.5s12.5 5.575 12.5 12.5a12.685 12.685 0 0 1-.1529 1.9691l.9537.5506-15.6454 
                    27.0986-.1554-.0897V65.5h-28.7285c-7.318 9.1548-18.587 15-31.2715 
                    15s-23.9535-5.8452-31.2715-15H15.5v-2.8059l-.0937.0437-8.8727-19.0274C2.912 41.5258.5 37.5549.5 33c0-6.925 
                    5.575-12.5 12.5-12.5S25.5 26.075 25.5 33c0 .9035-.0949 1.784-.2753 2.6321L29.8262 45.5h92.2098z`
                },
                data: [
                  {
                    coords: [
                      [110, 456],
                      [124, 450],
                      [123, 389],
                      [61, 386],
                      [61, 72],
                      [258, 72],
                      [260, 336],
                      [280, 410],
                      [275, 528],
                      [111, 552],
                      [118, 701],
                      [221, 758],
                      [307, 742],
                      [366, 560],
                      [492, 560],
                      [498, 827],
                      [294, 827],
                      [282, 868]
                    ]
                  }
                ]
              }
            ]
          };
          myChart.setOption(option);
        })
        .catch(error => {
          console.error('Error fetching SVG:', error);
        })
      option && myChart.setOption(option);
    }
  })
})

</script>
